﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace CallGen
{
    class Program
    {
        static MD5 md5 = new MD5CryptoServiceProvider();
        static Random r = new Random();

        static string ownPhone = "";
        static string provider = "";
        static DateTime fromDate = new DateTime();
        static DateTime toDate = new DateTime();
        static DateTime cursorDate = new DateTime();
        static List<List<string>> freq = new List<List<string>>();
        static List<string> t0 = new List<string>(); //0:00 - 2:00
        static List<string> t1 = new List<string>(); //2:00 - 6:00
        static List<string> t2 = new List<string>(); //6:00 - 9:00
        static List<string> t3 = new List<string>(); //9:00 - 12:00
        static List<string> t4 = new List<string>(); //12:00 - 17:00
        static List<string> t5 = new List<string>(); //17:00 - 22:00
        static List<string> t6 = new List<string>(); //22:00 - 24:00

        static List<int> xFrom = new List<int>();
        static List<int> xTo = new List<int>();
        static List<string> transaction = new List<string>();

        static void Main(string[] args)
        {
            freq.Add(t0);
            freq.Add(t1);
            freq.Add(t2);
            freq.Add(t3);
            freq.Add(t4);
            freq.Add(t5);
            freq.Add(t6);

            if (args.Length > 0)
            {

                string filename = args[0];

                GenTransactionFromCsv(filename);
                SaveTransactionToCsv(filename.Replace(".csv", "-ez.csv"));
            }
            else
            {
                Console.WriteLine("no input file");
                Console.ReadLine();
            }
            

        }

        static void GenTx(int t)
        {
            TimeSpan span = new TimeSpan(0, GetRandNum(xFrom[t], xTo[t]), 0);

            cursorDate = cursorDate.Add(span);

            string stx = freq[t][GetRandNum(0, freq[t].Count - 1)];
            if (stx.Trim().ToLower() != "x")
            {
                transaction.Add("'" + ownPhone + "," + provider + "," + GenRecord(stx));
            }
        }

        static void SaveTransactionToCsv(string filename)
        {
            StreamWriter sw = new StreamWriter(filename);

            sw.WriteLine("call_form,from_network,call_to,to_network,date,time,minutes");
            foreach (string tx in transaction)
            {
                sw.WriteLine(tx);
            }

            sw.Close();
            
        }

        static void GenTransactionFromCsv(string filename)
        {
            ReadCsv(filename);
            cursorDate = new DateTime(fromDate.Year, fromDate.Month, fromDate.Day);

            while (cursorDate < toDate)
            {
                int h = cursorDate.Hour;

                if (h >= 22)
                {
                    GenTx(6);
                }
                else if (h >= 17)
                {
                    GenTx(5);
                }
                else if (h >= 12)
                {
                    GenTx(4);
                }
                else if (h >= 9)
                {
                    GenTx(3);
                }
                else if (h >= 6)
                {
                    GenTx(2);
                }
                else if (h >= 2)
                {
                    GenTx(1);
                }
                else
                {
                    GenTx(0);
                }
            }
        }

        static void ReadCsv(string filename)
        {
            StreamReader sr = new StreamReader(filename);
            // for set encoding
            // StreamReader sr = new StreamReader(@"file.csv", Encoding.GetEncoding(1250));

            string strline = "";
            string[] texts = null;
            int line = 0;
            while (!sr.EndOfStream)
            {
                line++;
                strline = sr.ReadLine();
                texts = strline.Split(',');
                if (texts.Length >= 7)
                {
                    switch (line)
                    {
                        case 1:
                            {
                                //Phone
                                ownPhone = texts[1].Substring(1); ;
                               
                            }break;
                        case 2:
                            {
                                //Provider
                                provider = GenServ(texts[1], ownPhone);
                            }break;
                        case 3:
                            {
                                fromDate = GenDate(texts[1].Substring(1));
                            }break;
                        case 4:
                            {
                                toDate = GenDate(texts[1].Substring(1));
                            }break;
                        case 5:
                            {
                            }break;
                        case 6:
                            {
                                int[] dur = new int[]{120, 240, 180, 180, 300, 300, 120};
                                for (int i = 0; i < 7; i++)
                                {
                                    if (texts[i].Trim().Length >= 1)
                                    {
                                        int freq = int.Parse(texts[i]);
                                        freq = freq > 0 ? freq : 1;

                                        int wait = dur[i]/freq;

                                        xFrom.Add( wait *5/6);
                                        xTo.Add( wait*8/6);
                                    }
                                }
                            } break;
                        default:
                            {
                                for (int i = 0; i < 7; i++)
                                {
                                    if (texts[i].Trim().Length >= 1)
                                    {
                                        freq[i].Add(texts[i]);
                                    }
                                }
                            }break;
                    }
                }
            }
            sr.Close();
        }

        static string GenRecord(string sample)
        {
            string[] samples = sample.Split(new char[]{'.'});
            string name = samples[0];
            string serv = samples[1];
            string min = samples[2];

            int themin = GenMin(min);

            string record = "'" + GenNum(name, serv) + "," + GenServ(serv, name) + ","
                + "'" + cursorDate.ToString("yyyy-MM-dd") + ","
                + cursorDate.ToString("HH:mm") +","
                + themin;

            cursorDate = cursorDate.Add(new TimeSpan(0, themin, 0));

            return record;
        }

        static DateTime GenDate(string strDate)
        {
            string[] strs = strDate.Split(new char[] { '-' });
            return new DateTime(int.Parse(strs[2]), int.Parse(strs[1]), int.Parse(strs[0]));
        }

        static int GenMin(string min)
        {
            int themin = 1;

            string[] rex = min.Split(new char[] { '-' });
            if (rex.Length > 1)
            {
                int start = int.Parse(rex[0]);
                int end = int.Parse(rex[1]);
                themin = GetRandNum(Math.Min(start,end), Math.Max(start,end));
            }
            else if (rex.Length == 1)
            {
                int total = int.Parse(rex[0]);
                themin = GetRandNum(1, total - 1);
            }
            else
            {
                int total = 30;
                themin = GetRandNum(1, total - 1);

            }


            return themin;
        }

        static string GenServ(string serv, string name)
        {
            string prov = "dtac";
            switch (serv.ToLower())
            {
                case "a": prov ="ais" ;break;
                case "d": prov = "dtac"; break;
                case "t": prov = "tmove"; break;
                case "h": prov = "home"; break;
                default:
                    {
                        int x = 0;
                        for (int i = 0; i < name.Length; i++)
                        {
                            x += (int)(name[i]);
                        }
                           
                        int s = x % 3;
                        switch (s)
                        {
                            case 0: prov="ais"; break;
                            case 1: prov = "dtac"; break;
                            case 2: prov = "tmove"; break;
                            default: prov = "dtac"; break;
                        }
                    };break;
            }

            return prov;
        }

        static string GenNum(string name, string serv)
        {
            byte[] paintext = ASCIIEncoding.Default.GetBytes(name);
            byte[] cypher = md5.ComputeHash(paintext);

            string number = "";

            for (int i=0; i<8; i++)
            {
                number += cypher[i];
            }

            string phone = "";

            if (serv.Trim().ToLower() == "h")
            {
                phone = "02" + number.Remove(7);
            }
            else
            {
                phone = "08" + number.Remove(8);
            }

            return phone;
        }

        static int GetRandNum(int iStart, int iEnd)
        {
            if (iStart >= iEnd)
            {
                return iStart;
            }
            else
            {

                int i = r.Next(iStart, iEnd * iEnd);
                i = i / iEnd + 1;
                return i;
            }

        }
    }
}
